from __future__ import annotations
from abc import ABC, abstractmethod
from typing import override


class Pizza(ABC):
    def __init__(self):
        self._description = "Basic Pizza"

    def get_description(self):
        return self._description

    @abstractmethod
    def cost(self) -> float:
        ...


class ToppingDecorator(Pizza, ABC):
    def __init__(self, pizza: Pizza):
        super().__init__()
        self._pizza: Pizza = pizza

    @abstractmethod
    def get_description(self):
        ...


class Cheese(ToppingDecorator):
    def get_description(self):
        return self._pizza.get_description() + ", Cheese"

    def cost(self) -> float:
        return self._pizza.cost()


class Olives(ToppingDecorator):
    def get_description(self):
        return self._pizza.get_description() + ", Olives"

    def cost(self) -> float:
        return self._pizza.cost() + 30


class ThickCrustPizza(Pizza):
    def __init__(self):
        super().__init__()
        self._description = "Thick crust pizza, with tomato sauce"

    def cost(self) -> float:
        return 7.99


class ThinCrustPizza(Pizza):
    def __init__(self):
        super().__init__()
        self._description = "Thin crust pizza, with tomato sauce"

    def cost(self) -> float:
        return 7.99


if __name__ == '__main__':
    pizza = ThinCrustPizza()
    cheese_pizza = Cheese(pizza)
    greek_pizza = Olives(pizza)

    pizza2 = ThickCrustPizza()
    cheese_pizza2 = Cheese(pizza2)
    greek_pizza2 = Olives(pizza2)

    print(f"{greek_pizza.get_description()} ${greek_pizza.cost()}")
    print(f"{cheese_pizza.get_description()} ${cheese_pizza.cost()}")
    print(f"{greek_pizza2.get_description()} ${greek_pizza2.cost()}")
    print(f"{cheese_pizza2.get_description()} ${cheese_pizza2.cost()}")

    another_pizza = Cheese(greek_pizza)
    print(f"{another_pizza.get_description()} ${another_pizza.cost()}")
